
--for table
function table_add_integer_8(dstTable,value)
	local newValue = 0
	
	if(type(value) == "number") then
		if(math.type(value) == "integer") then
			newValue = value
		else
			newValue = math.floor(value)
		end
		
		table.insert(dstTable,newValue&0xFF);
	end
end

function table_add_integer_16(dstTable,value,endian)
	local newValue = 0
	
	if(type(value) == "number") then
		if(math.type(value) == "integer") then
			newValue = value
		else
			newValue = math.floor(value)
		end
		
		if(endian == 1) then
			--little endian
			table.insert(dstTable,newValue&0xFF);
			table.insert(dstTable,(newValue>>8)&0xFF);
		else
			--big endian
			table.insert(dstTable,(newValue>>8)&0xFF);
			table.insert(dstTable,newValue&0xFF);
		end
	end
end

function table_add_integer_32(dstTable,value,endian)
	local newValue = 0
	
	if(type(value) == "number") then
		if(math.type(value) == "integer") then
			newValue = value
		else
			newValue = math.floor(value)
		end
		
		if(endian == 1) then
			--little endian
			table.insert(dstTable,newValue&0xFF);
			table.insert(dstTable,(newValue>>8)&0xFF);
			table.insert(dstTable,(newValue>>16)&0xFF);
			table.insert(dstTable,(newValue>>24)&0xFF);
		else
			--big endian
			table.insert(dstTable,(newValue>>24)&0xFF);
			table.insert(dstTable,(newValue>>16)&0xFF);
			table.insert(dstTable,(newValue>>8)&0xFF);
			table.insert(dstTable,newValue&0xFF);
		end
	end
end

function table_add_integer_auto(dstTable,value,endian)
	local newValue = 0
	
	if(type(value) == "number") then
		if(math.type(value) == "integer") then
			newValue = value
		else
			newValue = math.floor(value)
		end
		
		if(newValue <= 0xFF) then
			table_add_integer_8(dstTable,newValue)
		elseif (newValue <= 0xFFFF) then
			table_add_integer_16(dstTable,newValue,endian)
		else
			table_add_integer_32(dstTable,newValue,endian)
		end
	end
end

function table_add_string(dstTable,value)
	local length=string.len(value);
	for i=1,length,1 do
		table.insert(dstTable,string.byte(value,i));		
	end   
end

function table_add_table(dstTable,value)
	for k,v in ipairs(value) do
		table.insert(dstTable,v);		
	end   
end

function table_add_string_or_table(dstTable,value)
	local valueType = type(value)
	if(valueType == "string") then
		table_add_string(dstTable,value)
	elseif(valueType == "table") then
		table_add_table(dstTable,value)
	end
end

function table_to_string(srcTable)
	local dstString = ""
	for k,v in ipairs(srcTable) do
		dstString=dstString..string.char(v);		
	end
	
	return dstString
end

--CRC16
function invert_8(iValue)
	local nValue = 0
	
	--低4位
	for i=1,4,1 do
		nValue = nValue | ((iValue<<(8-i*2+1))&(0x01<<(8-i)))
	end
	
	--高4位
	for i=1,4,1 do
		nValue = nValue | ((iValue>>(i*2-1))&(0x01<<(4-i)))
	end
	
	return nValue
end

function invert_16(iValue)
	local nValue = 0
	
	--低8位
	for i=1,8,1 do
		nValue = nValue | ((iValue<<(16-i*2+1))&(0x01<<(16-i)))
	end
	
	--高8位
	for i=1,8,1 do
		nValue = nValue | ((iValue>>(i*2-1))&(0x01<<(8-i)))
	end
	
	return nValue
end

function crc16_modbus(srcTable)
	local crc = 0xFFFF
	local poly = 0x8005
	local xorout = 0x0000
	
	for k,v in ipairs(srcTable) do
		crc = crc ~ (invert_8(v) << 8)
		for j=1,8,1 do
			if(crc&0x8000 == 0x8000) then
				crc = ((crc << 1)&0xFFFF) ~ poly
			else
				crc = (crc << 1)&0xFFFF
			end
		end
	end
	
	crc = invert_16(crc)
	crc = crc ~ xorout
	
	return crc
end

----道通----
    --打包命令,最大数据长度255--
function dt_pack_command(DA,CMD,DATA)
	local packet = {}
	
	--显示屏地址
	table_add_integer_8(packet,DA)
	--协议版本
	table_add_integer_8(packet,0x64)
	--包序号
	table_add_integer_16(packet,0xFFFF,1)
	--指令ID
	table_add_integer_8(packet,CMD)
	--数据长度
	table_add_integer_8(packet,#DATA)
	--数据内容
	table_add_string_or_table(packet,DATA)
	--校验域
	table_add_integer_16(packet,crc16_modbus(packet),1)
	
	return packet
end

    --设置时间--
function dt_set_time(DA)
	local dateTable = os.date("*t")
	local data = {}

	table_add_integer_16(data,dateTable["year"],1)
	table_add_integer_8(data,dateTable["month"])
	table_add_integer_8(data,dateTable["day"])
	table_add_integer_8(data,dateTable["wday"])
	table_add_integer_8(data,dateTable["hour"])
	table_add_integer_8(data,dateTable["min"])
	table_add_integer_8(data,dateTable["sec"])

	SendSerialData(0,dt_pack_command(DA,0x05,data))
end

    --设置音量-- 10~100
function dt_set_volume(DA,VOL)
	local data = {}

	table_add_integer_8(data,VOL)

	SendSerialData(0,dt_pack_command(DA,0x0D,data))
end

    --临时显示-- 0~60个字节
function dt_display_temp_kernel(DA,TWID,ETM,ETS,GST,DT,FINDEX,DRS,TC,TEXT)
	local data = {}
	local TL = #TEXT
	
	if(TL > 254) then
		print("txt is too long:"..TL.." > 254!")
		return
	end
	
	--TWID,行号
	table_add_integer_8(data,TWID)
	--ETM,文字显示方式
	table_add_integer_8(data,ETM)
	--ETS,文字进入的速度,1~32
	table_add_integer_8(data,ETS)
	--GST,界面显示时间,0~255
	table_add_integer_8(data,GST)
	--DT,文字停留的时间,0~255
	table_add_integer_8(data,DT)
	--RA1[2],保留
	table_add_integer_16(data,0x0001,1)
	--FINDEX,字体索引值
	table_add_integer_8(data,FINDEX)
	--DRS,显示的次数,0~255
	table_add_integer_8(data,DRS)
	--TC[4],文字的颜色值
	--table_add_table(data,TC)
	table_add_integer_32(data,TC,1)
	--RA2[4],保留
	table_add_integer_32(data,0x00000000,1)
	--TL,文字长度
	table_add_integer_8(data,TL)
	--R1,保留
	table_add_integer_8(data,0x00)
	--TEXT,	显示的文字内容
	table_add_string_or_table(data,TEXT)
	
	SendSerialData(0,dt_pack_command(DA,0x62,data))
end

function dt_display_temp(DA,line,duration,color,text)
	dt_display_temp_kernel(DA,line,0x15,1,duration,0,3,0,color,text)
end

    --广告内容-- 0~60个字节
function dt_display_advertisement_kernel(DA,TWID,ETM,ETS,DT,FINDEX,TC,TEXT)
	local data = {}
	local TL = #TEXT
	
	if(TL > 254) then
		print("txt is too long:"..TL.." > 254!")
		return
	end
	
	--TWID,行号
	table_add_integer_8(data,TWID)
	--R1,保留
	table_add_integer_8(data,0x00)
	--R2,保留
	table_add_integer_8(data,0x0C)
	--ETM,文字显示方式
	table_add_integer_8(data,ETM)
	--ETS,文字进入的速度,1~32
	table_add_integer_8(data,ETS)
	--R3,保留
	table_add_integer_8(data,0x00)
	--DT,文字停留的时间,0~255
	table_add_integer_8(data,DT)
	--RA1[2],保留
	table_add_integer_16(data,0x0000,1)
	--FINDEX,字体索引值
	table_add_integer_8(data,FINDEX)
	--TC[4],文字的颜色值
	--table_add_table(data,TC)
	table_add_integer_32(data,TC,1)
	--RA2[4],保留
	table_add_integer_32(data,0x00000000,1)
	--TL,文字长度
	table_add_integer_8(data,TL)
	--R3,保留
	table_add_integer_8(data,0x00)
	--TEXT,	显示的文字内容
	table_add_string_or_table(data,TEXT)
	
	SendSerialData(0,dt_pack_command(DA,0x67,data))
end

function dt_display_advertisement(DA,line,color,text)
	dt_display_advertisement_kernel(DA,line,0x15,1,5,3,color,text)
end

    --语音播报-- 1~254个字节
function dt_speech(DA,OTP,TEXT)
	local data = {}
	local txtLen = #TEXT
	
	--OTP
	 --0 添加到语音队列但是不开始播放
	 --1 添加到语音队列并且开始播放
	 --2 先清除队列，再添加新语音到队列，然后开始播放
	
	if(txtLen > 254) then
		print("txt is too long:"..txtLen.." > 254!")
		return
	end
	
	--选项
	table_add_integer_8(data,OTP)
	--内容
	table_add_string_or_table(data,TEXT)
	
	SendSerialData(0,dt_pack_command(DA,0x30,data))
end

function dt_speechData_add(data,text)
	local dataLen = #data
	
	if(dataLen==0) then
		table_add_string_or_table(data,text)
	else
		table_add_string_or_table(data,",")
		table_add_string_or_table(data,text)
	end
end

-----全局变量-------
-- deviceInfo
-- 当前时间 deviceInfo["curTime"]
-- 通道类型 deviceInfo["channelType"]
-- 通道名称 deviceInfo["channelName"]

-- 全局变量carInfo
-- 车牌 carInfo["plate"]
-- 颜色 carInfo["color"]
-- 可信度 carInfo["reliability"]
-- 车辆类型 carInfo["carType"]
-- 以下字段当 carType不为0时有效
---- 是否过期 carInfo["isExpried"]
---- 用户名 carInfo["userName"]
---- 起始时间 carInfo["beginTime"]
---- 结束时间 carInfo["endTime"]
---- 剩余时长 carInfo["leftTime"]

-----接口-------

local ledAddr = 0x00

function OnStartup()
	dt_set_time(ledAddr)
	
	OnDeviceInfoChange()
end

function OnDeviceInfoChange()
	if(deviceInfo["channelType"] == 0) then
		--出口
		dt_display_advertisement(ledAddr,0,0xFF,"20`Y-`M-`D `H:`N:`S 星期`V 智慧停车 车牌识别")
		dt_display_advertisement(ledAddr,1,0xFF,"一路平安")
		dt_display_advertisement(ledAddr,2,0xFF,"一车一杆")
		dt_display_advertisement(ledAddr,3,0xFF,"自动识别")
	else
		--入口
		dt_display_advertisement(ledAddr,0,0xFF,"20`Y-`M-`D `H:`N:`S 星期`V 智慧停车 车牌识别")
		dt_display_advertisement(ledAddr,1,0xFF,"欢迎光临")
		dt_display_advertisement(ledAddr,2,0xFF,"一车一杆")
		dt_display_advertisement(ledAddr,3,0xFF,"自动识别")
	end
end

function OnCarCome()
	local data={}
	local carTypeName=0
	local isShow=0
	
	carTypeName=GetCarTypeName(carInfo["carType"])
	
	if(type(deviceInfo["serverState"]) == "nil" ) then
		isShow=1
	elseif(deviceInfo["serverState"] == 1) then
		isShow=1
	end
	
	if(isShow == 1) then
		if(deviceInfo["channelType"] == 0) then
			--出口
			  --显示
			dt_display_temp(ledAddr,0,10,0xFF,carTypeName)
			dt_display_temp(ledAddr,1,10,0xFF,carInfo["plate"])
			if(carInfo["carType"]==0) then
				dt_display_temp(ledAddr,2,10,0xFF,"禁止通行")
			else
				dt_display_temp(ledAddr,2,10,0xFF,"一路平安")
			end

			  --语音播报
			dt_speechData_add(data,GetCarTypeVoice(carInfo["carType"]))
			dt_speechData_add(data,carInfo["plate"])
			if(carInfo["carType"]==0) then
				dt_speechData_add(data,"禁止通行")
			else
				dt_speechData_add(data,"一路平安")
			end
			dt_speech(ledAddr,1,data)
		else
			--入口
			  --显示
			dt_display_temp(ledAddr,0,10,0xFF,carTypeName)
			dt_display_temp(ledAddr,1,10,0xFF,carInfo["plate"])
			if(carInfo["carType"]==0) then
				dt_display_temp(ledAddr,2,10,0xFF,"禁止通行")
			else
				dt_display_temp(ledAddr,2,10,0xFF,"欢迎光临")
			end
			
			  --语音播报
			dt_speechData_add(data,GetCarTypeVoice(carInfo["carType"]))
			dt_speechData_add(data,carInfo["plate"])
			if(carInfo["carType"]==0) then
				dt_speechData_add(data,"禁止通行")
			else
				dt_speechData_add(data,"欢迎光临")
			end
			dt_speech(ledAddr,1,data)
		end
	end
end

function GetCarTypeName(carType)
	local name=""

	if(carType == 0) then
		name="临时车"
	elseif (carType == 1) then
		name="VIP车"
	elseif (carType == 2) then
		name="月租车"
	elseif (carType == 3) then
		name="充值车"
	elseif (carType == 4) then
		name="时租车"
	elseif (carType == 5) then
		--name="产权车"
		name="内部车"
	end
	
	return name
end

function GetCarTypeVoice(carType)
	local voice={}

	if(carType == 0) then
		table_add_string(voice,"临时车")
	elseif (carType == 1) then
		table_add_string(voice,"会员车")
	elseif (carType == 2) then
		table_add_string(voice,"月租车")
	elseif (carType == 3) then
		table_add_string(voice,"储值车")
	elseif (carType == 4) then
		table_add_string(voice,"时租车") -- 时租车
	elseif (carType == 5) then
		table_add_string(voice,"内部车") 
	end
	
	return voice
end

